package com.thread.queuelog;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class NodeList<T> {
	private Node<T> head;
	private Node<T> finis;
	private AtomicInteger count = new AtomicInteger();
	public volatile int length = 0;
	ReadWriteLock lock = new ReentrantReadWriteLock();
	public void add(T value){
		lock.writeLock().lock();
		if(head == null){
			head = new Node<T>(value);
			finis = head;
		}else{
			finis = new Node<T>(finis, value);
		}
		lock.writeLock().unlock();
		length = count.incrementAndGet();
		nosleep();
	}
	
	public T pop(){
		lock.readLock().lock();
		if(head == null){
			lock.readLock().unlock();
			if(!sleep()){
				return null;
			}
			lock.readLock().lock();
		}
		Node<T> first = head;
		head = first.next;
		first.next = null;
		lock.readLock().unlock();
		length = count.decrementAndGet();
		return first.getValue();
	}
	public int size(){
		return count.get();
	}
	private Object sleepLock = new Object();
	public void nosleep(){
		synchronized (sleepLock) {
			sleepLock.notify();
		}
	}
	public void close(){
		synchronized (sleepLock) {
			sleepLock.notifyAll();
		}
	}
	public boolean sleep(){
		synchronized (sleepLock) {
			try {
				sleepLock.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			return head!=null;
		}
	}
}
